package cloud.xiangyixiang.www.spring.boot.java.basics.controller;

import cloud.xiangyixiang.www.spring.boot.java.basics.service.IFeature;
import cloud.xiangyixiang.www.spring.boot.java.basics.service.IFunction;
import cloud.xiangyixiang.www.spring.boot.java.basics.service.impl.IFunctionImpl;
import cloud.xiangyixiang.www.spring.boot.java.basics.service.impl.ISchoolImpl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * <p>
 * JAVA8 Lambda 表达式
 * </p>
 *
 * @author zhixinglu
 * @date 2023/9/16 16:30
 */
public class Java8LambdaController {


    public static void main(String[] args) {

        test1();

        test2();

        test3();

        test4();

        test5();

        test6(10,()->(int)(Math.random()*100));

        String str1 = test7("abc", (str)->str.toUpperCase());
        System.out.println(str1);
        str1 = test7("  abc  ", (str)->str.trim());
        System.out.println(str1);
        System.out.println();


        List<String> list1 = Arrays.asList("hello","FanZaiYing","Lambda","www","xr","ar");
        List<String> result1 = test8(list1,(str)->str.length() > 2);
        System.out.println(result1);
        System.out.println();

        test9();

        test10();

        test11();

        test12();

        test13();

        System.out.println("与函数式接口Predicate配合:============");
        System.out.println("languages：Java、Python、scala、Shell、R");
        List<String> languages = Arrays.asList("Java", "Python", "scala", "Shell", "R");
        System.out.println("以J开头的结果：");
        test14(languages,x -> x.startsWith("J")); //Java
        System.out.println("以a结尾的结果：");
        test14(languages,x -> x.endsWith("a")); //Java,scala
        System.out.println("判断是否为true：");
        test14(languages,x -> true); //Java,Python,scala,Shell,R
        System.out.println("判断是否为false：");
        test14(languages,x -> false); //
        System.out.println("判断字符长度大于4的结果：");
        test14(languages,x -> x.length() > 4);//Python,scala,Shell,
        System.out.println();

        test15();

        test16();
    }

    /**
     * 详情介绍
     */
    private static void description(){
        System.out.println("详情介绍： ================");
        System.out.println("java是面向对象的，但是为了写起来方便，需要向一个方法传递一个方法，但是实际上并不能传递方法，而是传递了只有一个抽象方法的接口的实现类的对象，这样就实现了类似的交付方法了，其实lanmada就是一个对象。");
        System.out.println();
    }

    /**
     * 普通线程启动
     */
    private static void test1(){
        System.out.println("替代匿名内部类:==========");

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("普通，线程启动");
            }
        };
        runnable.run();

        System.out.println();
    }

    /**
     * Lambda 线程启动 无参数 无返回值
     */
    private static void test2(){
        System.out.println("Lambda 线程启动 无参数 无返回值：==============");
        //“->”左边只有一个小括号，表示无参数，右边是Lambda体(就相当于实现了匿名内部类里面的方法了，(即就是一个可用的接口实现类了。))
        Runnable runnable = ()-> System.out.println("Lambda 表达式方式，线程启动");
        runnable.run();

        System.out.println();
    }

    /**
     * Lambda表达式, 有一个参数，并且无返回值
     */
    private static void test3() {
        System.out.println("Lambda表达式， 有一个参数，并且无返回值: ============");
        // 这个e就代表所实现的接口的方法的参数，
        Consumer<String> consumer = e -> System.out.println("Lambda 表达式方式，" + e);
        consumer.accept("传入参数 1");
        consumer.accept("传入参数 2");

        System.out.println();
    }

    /**
     * 有两个以上的参数，有返回值，并且 Lambda 体中有多条语句
     */
    public static void test4() {
        System.out.println("Lambda表达式， 有两个以上的参数，有返回值，并且 Lambda 体中有多条语句");
        //Lambda 体中有多条语句，记得要用大括号括起来
        Comparator<Integer> com = (x, y) -> {
            System.out.println("比较整型大小，函数式接口");
            return Integer.compare(x, y);
        };
        int compare = com.compare(100, 244);
        System.out.println("有两个以上的参数，有返回值," + compare);

        System.out.println();
    }


    /**
     * 若 Lambda 体中只有一条语句， return 和 大括号都可以省略不写
     */
    public static void test5() {
        System.out.println("Lambda表达式，若 Lambda 体中只有一条语句， return 和 大括号都可以省略不写");
        Comparator com = (x, y) -> Integer.compare(100, 244);
        System.out.println(Integer.compare(100, 244));

        System.out.println();
    }

    /**
     * Lambda表达式作为参数
     * @param num {@link int} number of
     * @param sup {@link Supplier<Integer>}
     * @return
     */
    public static void test6(int num, Supplier<Integer> sup){
        System.out.println("Lambda表达式, 结果作为参数：=============");
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            Integer e = sup.get();
            list.add(e);
        }
        System.out.println(list);
        System.out.println();
    }

    /**
     * Function 函数式接口
     * @param str {@link String}
     * @return String
     */
    private static String test7(String str, Function<String,String>fun){
        System.out.println("函数式接口:===========");
        return fun.apply(str);
    }

    /**
     * Predicate 断言式接口
     *
     *  判断一些字符串数组判断长度>2的字符串
     * @param list {@link List<String>}
     * @param pre {Predicate<String>}
     * @return List<String>
     */
    public static List<String> test8(List<String> list, Predicate<String> pre){
        System.out.println("Predicate 断言式接口:================");
        ArrayList<String> arrayList = new ArrayList<>();
        for(String str:list){
            if(pre.test(str)) {
                arrayList.add(str);
            }
        }
        return arrayList;
    }

    /**
     *
     */
    public static void test9(){
        Comparator<Integer> comparator = (x,y)->Integer.compare(x,y);
        Comparator<Integer> comparator1 = Integer::compare;
        int compare = comparator.compare(1,2);
        int compare1 = comparator1.compare(1,2);
        System.out.println("compare:"+compare);
        System.out.println("compare1:"+compare1);
        System.out.println();
    }

    /**
     * 使用lambda表达式对集合进行迭代
     */
    private static void test10(){
        System.out.println("1.使用lambda表达式对集合进行迭代： =============");
        List<String> list = Arrays.asList("java","c#","javascript");
        // before java8
        for (String str:list){
            System.out.println("before java8," + str);
        }
        // after java8
        list.forEach(x-> System.out.println("after java8,"+x));

        System.out.println();
    }

    /**
     * 用lambda表达式实现map
     */
    private static void test11(){
        System.out.println("2.用lambda表达式实现map:=============");
        List<Double> list = Arrays.asList(10.0, 20.0, 30.0);
        list.stream().map(x -> x + x * 0.05).forEach(x -> System.out.println(x));
        System.out.println();
    }

    /**
     * 用lambda表达式实现map与reduce
     */
    private static void test12(){

        System.out.println("用lambda表达式实现map与reduce:=============");
        // before java8
        List<Double> cost = Arrays.asList(10.0, 20.0, 30.0);
        double sum = 0;
        for(double each:cost) {
            each += each * 0.05;
            sum += each;
        }
        System.out.println("before java8, " + sum);
        // after java8
        List<Double> list = Arrays.asList(10.0,20.0,30.0);
        double sum2 = list.stream().map(x -> x + x * 0.05).reduce((sum1,x) -> sum1 + x).get();
        System.out.println("after java8, " + sum2);

        System.out.println();
    }

    /**
     * filter操作
     *
     *  过滤List中大于25.0数据
     */
    private static void test13(){
        System.out.println("filter操作:=============");
        List<Double> cost = Arrays.asList(10.0, 20.0, 30.0, 40.0);
        List<Double> filteredCost = cost.stream().filter(x -> x > 25.0).collect(Collectors.toList());
        filteredCost.forEach(x -> System.out.println(x));
        System.out.println();
    }

    /**
     * 与函数式接口Predicate配合
     * @param languages {List<String>} 语言列表
     * @param condition {Predicate<String>} 匹配规则
     */
    private static void test14(List<String> languages, Predicate<String> condition){
        languages.stream().filter(x -> condition.test(x)).forEach(x -> System.out.println(x + " "));
        System.out.println();
    }

    /**
     * 函数式接口 静态方法
     */
    private static void test15(){
        System.out.println("函数式接口 静态方法：=========");

        IFunctionImpl functionImpl = new IFunctionImpl();
        functionImpl.study("java8");
        functionImpl.sleep(1);
        IFunction.play();
        //IFunction.sleep(1);

        System.out.println();
    }

    /**
     * 注意事项
     * 1. 当一个实现类实现了多个接口，多个接口里都有相同的默认方法时，实现类必须重写该默认方法，否则编译错误。
     * 2. 实现类使用super关键字指定使用哪个接口的默认方法。
     */
    private static void test16(){
        System.out.println("当一个实现类实现了多个接口，多个接口里都有相同的默认方法时，实现类必须重写该默认方法，否则编译错误。：=========");

        ISchoolImpl schoolImpl = new ISchoolImpl();
        schoolImpl.teaching("java8");
        schoolImpl.name("知行录");
        schoolImpl.studying("java8");

        schoolImpl.rest(15);

        System.out.println();
    }

    /**
     * 功能性接口功能
     */
    private static void test17(){
    }

}
